//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#ifndef __ELASTOS_IDEDRIVE_H__
#define __ELASTOS_IDEDRIVE_H__

#define DEVICENAME_IDEDRIVE             L"idedrive"

//
// IDEDrive
//
class IDEController;
class IDEPartition;

class PartitionInfo : public DLinkNode
{
public:
    PartitionInfo(
        uint_t uDeviceNo, uint32_t u32StartSector, uint32_t u32TotalSectors)
    {
        m_uDeviceNo         = uDeviceNo;
        m_u32StartSector    = u32StartSector;
        m_u32TotalSectors   = u32TotalSectors;
    }

public:
    uint_t      m_uDeviceNo;
    uint32_t    m_u32StartSector;
    uint32_t    m_u32TotalSectors;
};

class IDEDrive : public CDeviceDriver
{
public:
    CARAPI Read(
        /* [in] */ UInt64 u64Offset,
        /* [in] */ UInt32 bytesToRead,
        /* [out] */ MemoryBuf * pBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Write(
        /* [in] */ UInt64 u64Offset,
        /* [in] */ const MemoryBuf & buffer,
        /* [out] */ UInt32 * pBytesWritten,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Control(
        /* [in] */ Handle32 nControlCode,
        /* [in] */ const MemoryBuf & inBuffer,
        /* [out] */ MemoryBuf * pOutBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    virtual void Dispose();

public:
    ECode ReadSectors(
        uint32_t u32LogicalSectorNo, uint8_t *pu8Buffer,
        uint_t uNumberOfSectorsToRead, uint_t *puNumberOfSectorsRead);

    ECode WriteSectors(
        uint32_t u32LogicalSectorNo, uint8_t *pu8Buffer,
        uint_t uNumberOfSectorsToWrite, uint_t *puNumberOfSectorsWritten);

//_BUG_
    ECode ReadSectors(
        uint16_t u16CylinderNo, uint8_t u8HeadNo,
        uint8_t u8SectorNo, uint8_t *pu8Buffer,
        uint_t uNumberOfSectorsToRead, uint_t *puNumberOfSectorsRead);
//_BUG_
    ECode WriteSectors(
        uint16_t u16CylinderNo, uint8_t u8HeadNo,
        uint8_t u8SectorNo, uint8_t *pu8Buffer,
        uint_t uNumberOfSectorsToWrite, uint_t *puNumberOfSectorsWritten);

public:
    IDEDrive(IDEController *pController, uint_t uDeviceNo);

    PartitionInfo *GetPartitionInfo(uint_t uDeviceNo);

private:
    ECode InitPartitions();

    ECode InitPartition(
        uint32_t u32StartSectorNoOfPartTab, const Partition &partition);

    ECode ReadPartitionTable(
        uint32_t u32LogicalSectorNo,
        Partition parttab[c_uNumberOfPartTabEntries]);

public:
    IDEController   *m_pController;
    uint_t          m_uDeviceNo;
    uint_t          m_uDriveNo;

    uint_t          m_uNumberOfPartInfos;
    DLinkNode       m_partInfoListHead;
    uint32_t        m_u32StartSectorOfFirstExtPartTab;
};

#endif // __ELASTOS_IDEDRIVE_H__
